#ifndef CLONABLE_HPP
#define CLONABLE_HPP

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SmegTools/Debug/DebugNew.hpp>

namespace smeg {
    namespace tools {
        
////////////////////////////////////////////////////////////
/// Base class from which we can call clone
////////////////////////////////////////////////////////////
template <typename T>
class Clonable {
public:
    ////////////////////////////////////////////////////////////
    /// Virtual function to clone a class
    ///
    /// \return A pointer to a copy of this
    ///
    ////////////////////////////////////////////////////////////
    virtual T* Clone() const = 0;
};

    } // namespace tools
} // namespace smeg

////////////////////////////////////////////////////////////
/// Define that define the clone function for the class_name class with base class base_class_name
///
/// \return A pointer to a copy of this
///
////////////////////////////////////////////////////////////
#define DECLARE_CLONE_FUNC( class_name, base_class_name )                \
    virtual base_class_name* Clone() const {                            \
        return new class_name( static_cast<class_name const&>(*this) ); \
    }

///////////////////////////////////////////////////////////////////////////
//
// With these tools, clonable class can be created easily
// For a class to be clonable :
//
// 1)
// Inherit from Clonable
//
// 2)
// Put in your public section : DECLARE_CLONE_FUNC(your_class, class_derived_from_clonable)
// 
// EXAMPLE :
// // a.h
// class A : public Clonable<A>
// {
// public:
//      DECLARE_CLONE_FUNC(A, A)
// };
// 
// // b.h
// class B : public A 
// {
// public:
//      DECLARE_CLONE_FUNC(B, A)
// };
// 
// // c.h
// class C : public B 
// {
// public:
//      DECLARE_CLONE_FUNC(C, A) // A is the Clonable class, even if C inherit from B
// };
//
///////////////////////////////////////////////////////////////////////////

#include <SmegTools/Debug/DebugNewOff.hpp>

#endif // CLONABLE_HPP
